home *** CD-ROM | disk | FTP | other *** search
/ Aminet 39 / Aminet 39 (2000)(Schatztruhe)[!][Oct 2000].iso / Aminet / util / misc / cookietool.lha / cookietool / cdbsplit.c next >
Encoding:
C/C++ Source or Header  |  2000-07-18  |  11.4 KB  |  374 lines

  1. /*
  2.     cookietool is (c) 1995-2000 by Wilhelm Noeker (wnoeker@t-online.de)
  3.  
  4.     This program is free software; you can redistribute it and/or
  5.     modify it under the terms of the GNU General Public License as
  6.     published by the Free Software Foundation; either version 2 of the
  7.     License, or (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful, but
  10.     WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12.     General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program; if not, write to the Free Software
  16.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  17.     02111-1307 USA
  18.     
  19.  */
  20.  
  21.   
  22. /*========================================================================*\
  23.  |  File: cdbsplit.c                                   Date: 25 Oct 1997  |
  24.  *------------------------------------------------------------------------*
  25.  |    Split parts off your cookie database, by keyword, by line length,   |
  26.  |       by number of lines, or as groups of "similar" cookies.           |
  27.  | Expected file format is plain text with a "%%" line ending each cookie.|
  28.  |                     See help() for usage notes.                        |
  29.  |                                                                        |
  30. \*========================================================================*/
  31.  
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <ctype.h>
  36. #include "strstuff.h"
  37.  
  38. char version[] = "$VER: cdbsplit 2.3 (17.07.2000)";
  39. #define EOC "%%"                /* the cookie delimiter */
  40.  
  41.  
  42. #define FBUFSIZE 16384          /* we'll use larger file buffers */
  43. #define CBUFSIZE 32000L
  44. #define LBUFSIZE 2000
  45. #define NTARGET 10              /* max. number of keywords to search for */
  46. char line[LBUFSIZE];            /* large enough to hold the longest line */
  47. char cbuf[CBUFSIZE];            /* large enough to hold one complete cookie */
  48. char cbak[CBUFSIZE];            /* backup of the last cookie, to find groups */
  49. char uppercase[256];            /* conversion table */
  50.  
  51. int l_min = 1, l_max = 0, w_min = 1, w_max = 0;
  52. long n_min = 1, n_max = 0;
  53. int matchlen = 0;
  54. char *rtarget[NTARGET];         /* required keywords */
  55. char *otarget[NTARGET];         /* optional keywords */
  56. int required = 0, optional = 0;
  57.  
  58.  
  59. /* 
  60.  * print a help text and nag about illegal parameter <s> 
  61.  */
  62. void help( char *s )
  63. {
  64.   if( s )
  65.     printf( "illegal option '%s'\n", s );
  66.   printf( "usage:  cdbsplit [options] <cookiefile> <newfile>\n" );
  67.   printf( "where options are:\n" );
  68.   printf( " -k<keywd> / -K<keywd>  search for optional / required keyword\n" );
  69.   printf( " -l<lines> / -L<lines>  range for number of lines in a cookie\n" );
  70.   printf( " -w<width> / -W<width>  range for cookie line width\n" );
  71.   printf( " -n<no.>   / -N<no.>    range of cookie numbers\n" );
  72.   printf( " -m<m>     extract groups of cookies with <m> matching chars\n" );
  73.   printf( " -d[0-3]   how fussy about word delimiters? (default: 2) \n" );
  74.   printf( " -c        case sensitive comparisons\n" );
  75.   printf( " -x        extract only, do not modify the input file\n" );
  76.   printf( " -a        append to an existing output file\n" );
  77. }
  78.  
  79.  
  80.  
  81. int dispatch( char *cookie, int good, FILE *fp2, FILE *fp3 )
  82. {
  83.   long result = 1;
  84.   
  85.   if( good )
  86.     result = fprintf( fp2, "%s%s\n", cookie, EOC );
  87.   else if( fp3 )
  88.     result = fprintf( fp3, "%s%s\n", cookie, EOC );
  89.   if( result <= 0 )
  90.     {
  91.       printf( "\nfile error, aborted !!!\n" );
  92.       exit( 20 );
  93.     }
  94.   return good ? 1 : 0;
  95. }
  96.  
  97.  
  98. long filter_cookies( FILE *fp1, FILE *fp2, FILE *fp3 )
  99. /* scatter contents of <fp1> across <fp2> (hitfile) and <fp3> (dumpfile),
  100.  * return value is the number of cookies in the dumpfile
  101.  */
  102. {
  103.   long count = 0, hits = 0, cbuflen;
  104.   int ok = 0, ok2, lines, width, w, i;
  105.  
  106.   strcpy( cbak, "" );
  107.   strcpy( cbuf, "" );
  108.   cbuflen = lines = width = 0;
  109.   while( fgets( line, LBUFSIZE, fp1 ) )
  110.     {
  111.       if( strncmp( line, EOC, strlen( EOC ) ) == 0 )
  112.         {                       /* "end of cookie"-marker */
  113.           count++;
  114.           /* perform the checks: */
  115.           if( matchlen )        /* "similar cookies" mode */
  116.             {
  117.               ok2 = ok;
  118.               ok = (strn_cmp( cbak, cbuf, matchlen ) == 0);
  119.               if( *cbak )       /* skip the first loop */
  120.                 hits += dispatch( cbak, ok || ok2, fp2, fp3 );
  121.               strcpy( cbak, cbuf );
  122.             }
  123.           else                  /* standard mode */
  124.             {
  125.               ok = (lines >= l_min && width >= w_min && count >= n_min);
  126.               if( l_max )
  127.                 ok = ok && ( lines <= l_max );
  128.               if( w_max )
  129.                 ok = ok && ( width <= w_max );
  130.               if( n_max )
  131.                 ok = ok && ( count <= n_max );
  132.               if( ok )          /* string checks still necessary? */
  133.                 {
  134.                   if( required == 0 && optional > 0 )
  135.                     ok = 0;
  136.                   for( i = 0; i < required; i++ )
  137.                     ok = ok && (str_str( cbuf, rtarget[i] ) != NULL);
  138.                   for( i = 0; i < optional; i++ )
  139.                     ok = ok || (str_str( cbuf, otarget[i] ) != NULL);
  140.                 }
  141.               hits += dispatch( cbuf, ok, fp2, fp3 );
  142.             }
  143.           if( count % 100 == 0 )
  144.             {
  145.               printf( "%ld hits/%ld misses.\r", hits, count - hits );
  146.               fflush( stdout );
  147.             }
  148.           strcpy( cbuf, "" );   /* start a new cookie */
  149.           cbuflen = lines = width = 0;
  150.         }
  151.       else                      /* add a line to the current cookie */
  152.         {
  153.           w = strlen( line ) - 1;       /* don't count the "\n" */
  154.           if( (cbuflen += w) >= CBUFSIZE )
  155.             {
  156.               printf( "\ncookie too big (>%ld chars) \n", CBUFSIZE );
  157.               exit( 20 );
  158.             }
  159.           strcat( cbuf, line );
  160.           lines++;
  161.           if( w > width )
  162.             width = w;
  163.         }
  164.     }
  165.   if( matchlen )                /* one cookie still pending in this mode */
  166.     hits += dispatch( cbak, ok, fp2, fp3 );
  167.   printf( "Done, %ld hits out of %ld\n", hits, count );
  168.   return (count - hits);
  169. }
  170.  
  171.  
  172.  
  173. void confirm_options()
  174. /* tell the user what his options will do */
  175.   int flags, i;
  176.   
  177.   if( matchlen )
  178.     printf( "  searching for groups of cookies with "
  179.             "%d matching characters.\n", matchlen );
  180.   else
  181.     {
  182.       flags = 0xf;              /* what restrictions do apply? */
  183.       if( optional + required > 0 )
  184.         {
  185.           printf( "  search string%s: ", (optional + required > 1) ? "s" : "");
  186.           if( required > 1 && optional > 0 )
  187.             printf("(");
  188.           if( required > 0 )
  189.             {            
  190.               printf( "\"%s\"", rtarget[0] );
  191.               for( i = 1; i < required; i++ )
  192.                 printf( " && \"%s\"", rtarget[i] );
  193.             }
  194.           if( required > 1 && optional > 0 )
  195.             printf(")");
  196.           if( required > 0 && optional > 0 )
  197.             printf(" || ");
  198.           if( optional > 0 )
  199.             {
  200.               printf( "\"%s\"", otarget[0] );
  201.               for( i = 1; i < optional; i++ )
  202.                 printf( " || \"%s\"", otarget[i] );
  203.             }
  204.           printf( "\n" ); 
  205.         }
  206.       else
  207.         flags ^= 1;
  208.       if( l_max )
  209.         printf( "  looking for cookies %d - %d lines long.\n", l_min, l_max );
  210.       else if( l_min > 1 )
  211.         printf( "  looking for cookies at least %d lines long.\n", l_min );
  212.       else
  213.         flags ^= 2;
  214.       if( w_max )
  215.         printf( "  looking for cookies %d - %d columns wide.\n", w_min, w_max );
  216.       else if( w_min > 1 )
  217.         printf( "  looking for cookies at least %d columns wide.\n", w_min );
  218.       else
  219.         flags ^= 4;
  220.       if( n_max )
  221.         printf( "  considering cookies #%ld - #%ld only.\n", n_min, n_max);
  222.       else if( n_min > 1 )
  223.         printf( "  starting at cookie #%ld.\n", n_min );
  224.       else
  225.         flags ^= 8;
  226.       if( flags == 0 )
  227.         printf( "  no restrictions.\n" );
  228.     }
  229. }
  230.  
  231.  
  232. int main( int argc, char *argv[] )
  233. {
  234.   char *s;
  235.   char *name1 = NULL, *name2 = NULL, *name3 = "cdb_temp_kickme";
  236.   int append = 0, move = 1;
  237.   int case_sense = 0, bordermode = 2;
  238.   long dumped;
  239.   FILE *infile, *hitfile, *dumpfile;
  240.  
  241.   if( argc < 3 )
  242.     {
  243.       help( NULL );
  244.       return 5;
  245.     }
  246.   while( --argc )
  247.     {
  248.       s = *++argv;
  249.       if( *s != '-' )
  250.         {
  251.           if( name1 == NULL )
  252.             name1 = s;
  253.           else       
  254.             name2 = s;
  255.         }
  256.       else
  257.         {
  258.           s++;
  259.           switch( *s++ )
  260.             {
  261.             case 'k':
  262.               if( optional < NTARGET )
  263.                 otarget[ optional++ ] = s;
  264.               break;
  265.             case 'K':
  266.               if( required < NTARGET )
  267.                 rtarget[ required++ ] = s;
  268.               break;
  269.             case 'm':
  270.               matchlen = atoi( s );
  271.               break;
  272.             case 'l':
  273.               l_min = atoi( s );
  274.               break;
  275.             case 'L':
  276.               l_max = atoi( s );
  277.               break;
  278.             case 'w':
  279.               w_min = atoi( s );
  280.               break;
  281.             case 'W':
  282.               w_max = atoi( s );
  283.               break;
  284.             case 'n':
  285.               n_min = atol( s );
  286.               break;
  287.             case 'N':
  288.               n_max = atol( s );
  289.               break;
  290.             case 'a':
  291.               append = 1;
  292.               break;
  293.             case 'x':
  294.               move = 0;
  295.               break;
  296.             case 'c':
  297.               case_sense = 1;
  298.               break;
  299.             case 'd':
  300.               if( isdigit( *++s ) )
  301.                 bordermode = atoi( s );
  302.               else
  303.                 {
  304.                   help( argv[0] );
  305.                   return 5;
  306.                 }
  307.               break;
  308.             default:
  309.               help( argv[0] );
  310.               return 5;
  311.             }
  312.         }
  313.     }
  314.   str_setup( bordermode, case_sense ); /* !!! */
  315.   if( name1 == NULL || name2 == NULL )
  316.     {
  317.       help( NULL );
  318.       return 5;
  319.     }
  320.   if( !(infile = fopen( name1, "r" ) ) )
  321.     {
  322.       printf( "Can't open '%s' for input!\n", name1 );
  323.       return 10;
  324.     }
  325.   setvbuf( infile, NULL, _IOFBF, FBUFSIZE );
  326.   if( !append && (hitfile = fopen( name2, "r" )) )
  327.     {
  328.       printf( "Error: '%s' exists!  Use -a to append.\n", name2 );
  329.       return 10;
  330.     }
  331.   if( !(hitfile = fopen( name2, "a" )) )
  332.     {
  333.       printf( "Can't open '%s' for output!\n", name2 );
  334.       return 10;
  335.     }
  336.   setvbuf( hitfile, NULL, _IOFBF, FBUFSIZE );
  337.   if( move )
  338.     {
  339.       if( !(dumpfile = fopen( name3, "w" ) ) )
  340.         {
  341.           printf( "Can't open '%s' for output!\n", name3 );
  342.           return 10;
  343.         }
  344.       setvbuf( dumpfile, NULL, _IOFBF, FBUFSIZE );
  345.     }
  346.   else
  347.     dumpfile = NULL;
  348.   printf( "CdbSplit " );           
  349.   print_strstat();
  350.   printf( "%sing from '%s' to '%s',\n", move ? "Mov" : "Copy", name1, name2 );
  351.   confirm_options();            
  352.   /* OK, here we go: */
  353.   dumped = filter_cookies( infile, hitfile, dumpfile );
  354.   fclose( infile );
  355.   fclose( hitfile );
  356.   if( move )
  357.     {
  358.       fclose( dumpfile );
  359.       if( remove( name1 ) != 0 || rename( name3, name1 ) != 0 )
  360.         {
  361.           printf( "Couldn't overwrite the input file!  Your cookies are in '%s'.\n", name3 );
  362.           return 5;
  363.         }
  364.       if( dumped == 0 )
  365.         {
  366.           remove( name1 );
  367.           printf( "'%s' is now empty and has been deleted.\n", name1 );
  368.         }
  369.     }
  370.   return 0;
  371. }
  372.  
  373.